package com.example.demo.demo;

import java.util.Objects;

public class LamadaInterface {
    public interface itf<T, K, V> {
        void accept(T t, K k, V v);

        default itf<T, K, V> beforeAndThen(itf<? super T, ? super K, ? super V> beforeAccept, itf<? super T, ? super K, ? super V> afterAccept) {
            Objects.requireNonNull(beforeAccept);
            Objects.requireNonNull(afterAccept);
            return (t, k, v) -> {
                beforeAccept.accept(t, k, v);
                accept(t, k, v);
                afterAccept.accept(t, k, v);
            };
        }
    }

    itf<Integer, Integer, Integer> before;
    itf<String, String, String> after;


    public void setBefore(itf<Integer, Integer, Integer> before) {
        this.before = before;
    }


    public void setAfter(itf<String, String, String> after) {
        this.after = after;
    }

    public itf<Integer, Integer, Integer> getDefaultBefore() {
        return (i, j, k) -> {
            System.out.println(i + j + k);
        };
    }

    public itf<Integer, Integer, Integer> getDefaultAfter() {
        return (i, j, k) -> {
            System.out.println(i - j - k);
        };
    }

    public void excute() {
        int i = 1;
        int j = 1;
        int k = 1;
        if (before != null) {
            before.accept(i, j, k);
        }
        System.out.println("to do something...");

        String s = "hello";
        String u = "world";
        String v = "!!";
        if (after != null) {
            after.accept(s, u, v);
        }
    }

    public static void main(String[] args) {
        LamadaInterface main2 = new LamadaInterface();
        main2.setBefore(main2.getDefaultBefore());
        main2.setAfter((i, j, k) -> {
            System.out.println("tttt" + i.toString() + j.toString() + k.toString());
        });
        main2.excute();

        System.out.println("-------------------------------------");

        LamadaInterface extra = new LamadaInterface();
        itf<Integer, Integer, Integer> b = (i, j, k) -> {
            System.out.println(i * j * k);
        };
        extra.setBefore(b.beforeAndThen((i, j, k) -> {
            System.out.println("before accept start...");
            System.out.println("i=" + i + ",j=" + j + ",k=" + k);
            System.out.println("before accept end...");
        }, (i, j, k) -> {
            System.out.println("after accept start...");
            System.out.println("i=" + i + ",j=" + j + ",k=" + k);
            System.out.println("after accept end...");
        }));

        itf<String, String, String> a = (i, j, k) -> {
            System.out.println(i + j + k);
        };
        extra.setAfter(a.beforeAndThen((i, j, k) -> {
            System.out.println("before accept start...");
            System.out.println("before accept end...");
        }, (i, j, k) -> {
            System.out.println("after accept start...");
            System.out.println("after accept end...");
        }));
        extra.excute();
    }
}
